#include "ModBusTcpWorker.h"
#include "common/Utils.h"
#include <QDateTime>
#include <QThread>

#if TRADITION_TCP //传统的TCP
ModBusTcpWorker::ModBusTcpWorker(QObject *parent,bool isRTU):QObject(parent)/*, socket(new QTcpSocket(this))*/,m_RTU(isRTU),socket(nullptr),
    m_ProName(""),m_DevType(0),IPAddress(""),IPPort(0),cntSendIndex(0),WriteDataQueueIsEmpty(true),WriteDataQueueIsEmptyPre(true),logcnt(0)
{
    //connect(socket, &QTcpSocket::connected, this, &ModBusTcpWorker::onConnected);
    //connect(socket, &QTcpSocket::readyRead, this, &ModBusTcpWorker::onReadyRead);
    m_Connect = new QTimer(this);
    connect(m_Connect,&QTimer::timeout,this,&ModBusTcpWorker::timeoutLoopConnect);

    m_LoopReadTimer = new QTimer(this);
    connect(m_LoopReadTimer,&QTimer::timeout,this,&ModBusTcpWorker::timeoutReadHoldingRegisters);

    m_WriteQueueTimer = new QTimer(this);
    connect(m_WriteQueueTimer,&QTimer::timeout,this,&ModBusTcpWorker::timeoutWriteQueueRegisters);
}

ModBusTcpWorker::~ModBusTcpWorker()
{
    m_LoopReadTimer->stop();
    m_WriteQueueTimer->stop();
    //析构的时候断开连接
    if(socket->state() == QAbstractSocket::ConnectedState)
    {
        socket->disconnectFromHost();//断开连接
    }
}

void ModBusTcpWorker::slotSetProNameDevType(QString proName, int DevType)
{
    m_ProName = proName;
    m_DevType = DevType;
}

void ModBusTcpWorker::slotSetIPPort(QString address, short port)
{
    if(IPAddress !=address || IPPort!=port)
    {
        // 检查对象是否存在，如果存在则销毁并重新创建
        if (socket)
        {
            disconnect(socket, &QTcpSocket::connected, this, &ModBusTcpWorker::onConnected);
            disconnect(socket, &QTcpSocket::disconnected, this, &ModBusTcpWorker::onDisConnected);
            disconnect(socket, &QTcpSocket::readyRead, this, &ModBusTcpWorker::onReadyRead);
            delete  socket;
            socket = new QTcpSocket(this);
        }
        else
        {
            socket = new QTcpSocket(this);
        }
        connect(socket, &QTcpSocket::connected, this, &ModBusTcpWorker::onConnected);
        connect(socket, &QTcpSocket::disconnected, this, &ModBusTcpWorker::onDisConnected);
        connect(socket, &QTcpSocket::readyRead, this, &ModBusTcpWorker::onReadyRead);

        IPAddress = address;
        IPPort = port;
    }
}

void ModBusTcpWorker::slotFristReadStartAddressAndRegisterCount(QList<int> startAddress, QList<int> registerCount, int RegisterType)
{
    /*
    fristReadRegisterInfo.clear();
    if(startAddress.size() == registerCount.size())
    {
        QList<QPair<int,int> > InputRegistersInfo;
//        InputRegistersInfo << QPair<int,int>(4,2)  << QPair<int,int>(20,22);
        for(int i = 0 ; i < startAddress.size(); i++)
        {
            InputRegistersInfo << QPair<int,int>(startAddress.at(i),registerCount.at(i));
        }
        fristReadRegisterInfo.insert(RegisterType,InputRegistersInfo);
        qDebug() << "fristReadRegisterInfo:" << InputRegistersInfo;
    }
    else
    {
        qDebug() << "第一次连接需要去取的 寄存器起始地址和地址个数不对";
    }
    */

   // ReadStartAddress = startAddress;
    //ReadRegisterCount = registerCount;
//    readHoldingRegisters();
    if(startAddress.size() == registerCount.size())
    {
        for(int i = 0 ; i < startAddress.size();i++)
        {
            SendfristReadRegister << HandleAndSend(i+RegisterType*1000,0x01,RegisterType,startAddress.at(i),registerCount.at(i));
        }
    }
    else
    {
        qDebug() << "寄存器的起始地址和输入地址的个数不对";
    }

}

void ModBusTcpWorker::slotSetReadStartAddressAndRegisterCount(QList<int> startAddress, QList<int> registerCount, int RegisterType)
{
    /**********QMap*********
    ReadStartAddress = startAddress;
    ReadRegisterCount = registerCount;
//    readHoldingRegisters();
    if(ReadStartAddress.size() == ReadRegisterCount.size())
    {
        QList<QPair<int,int> > InputRegistersInfo;
//        InputRegistersInfo << QPair<int,int>(4,2)  << QPair<int,int>(20,22);
        for(int i = 0 ; i < ReadStartAddress.size(); i++)
        {
            InputRegistersInfo << QPair<int,int>(ReadStartAddress.at(i),ReadRegisterCount.at(i));
        }
        ReadRegisterInfo.insert(RegisterType,InputRegistersInfo);
        qDebug() << "ReadRegisterInfo:" << ReadRegisterInfo;
    }
    else
    {
        qDebug() << "寄存器的起始地址和输入地址的个数不对";
    }
    **********QMap*********/
    if(startAddress.size() == registerCount.size())
    {
        for(int i = 0 ; i < startAddress.size();i++)
        {
            SendReadRegister << HandleAndSend(i+RegisterType*100,0x01,RegisterType,startAddress.at(i),registerCount.at(i));
        }
    }
    else
    {
        qDebug() << "寄存器的起始地址和输入地址的个数不对";
    }

    cntSendIndex = 0;
}

void ModBusTcpWorker::slotStartConnection(bool isStart)
{
    if(isStart)
    {
        if(socket->state() != QAbstractSocket::ConnectedState)
        {
            socket->connectToHost(IPAddress, IPPort); // 连接到服务器
        }
    }
    else
    {
        if(socket->state() == QAbstractSocket::ConnectedState)
            socket->disconnectFromHost();
    }

}

void ModBusTcpWorker::slotAddWriteQueue(WriteData *data)
{
    if(socket->state() == QAbstractSocket::ConnectedState) // 服务端已连接则读取
    {
#if 0
        // 之前的写法加入队列
        m_WriteDataQueue.enqueue(data);
        if(!m_WriteQueueTimer->isActive())
            m_WriteQueueTimer->start(50);


#else
        if(m_RTU)
        {
            if(data->m_RegisterCount > 1)
            {
                QByteArray request;
                QDataStream stream(&request, QIODevice::WriteOnly);
                stream.setByteOrder(QDataStream::BigEndian);

                // 设备地址
                quint8 deviceAddress = 0x01;
                stream << deviceAddress;
                // 功能码
                quint8 functionCode = 0x10;
                stream << functionCode;
                // 寄存器起始地址
                stream << data->m_StartAddress;
                // 寄存器数量
                quint16 registerCount = data->m_RegisterCount;
                stream << registerCount;
                // 字节计数
                quint8 byteCount = registerCount * 2;
                stream << byteCount;
                // 寄存器值
                for (quint16 value : data->m_Data) {
                    stream << value;
                }
                // CRC校验

                //qDebug() << " request:" << ByteArraytoQString16bitShow(request);
                quint16 crc = swapBytes(calculateCRC(request));
                //qDebug() << "crc:" << printQuint16AsBytes(crc);
                stream << crc;
                qDebug() << " Muli write:" << ByteArraytoQString16bitShow(request);

                WriteQueue.enqueue(request);
                if(!WriteQueue.isEmpty())
                {
                    if(!m_WriteQueueTimer->isActive())
                        m_WriteQueueTimer->start(50);
                }
            }
            else if(data->m_RegisterCount == 1)
            {
                QByteArray request;
                QDataStream stream(&request, QIODevice::WriteOnly);
                stream.setByteOrder(QDataStream::BigEndian);

                // 设备地址
                quint8 deviceAddress = 0x01;
                stream << deviceAddress;
                // 功能码
                quint8 functionCode = 0x06;
                stream << functionCode;
                // 寄存器地址
                stream << data->m_StartAddress;
                // 寄存器值
                quint16 registerValue = 0xFFFF;
                if(!data->m_Data.isEmpty())
                    registerValue = data->m_Data.at(0); // 替换为你要写入的值
                stream << registerValue;

                // 计算CRC
                quint16 crc = swapBytes(calculateCRC(request));
                // 添加CRC到请求
                stream << crc;

                // 发送请求
                qDebug() << " sing write:" << ByteArraytoQString16bitShow(request);
                WriteQueue.enqueue(request);
                if(!WriteQueue.isEmpty())
                {
                    if(!m_WriteQueueTimer->isActive())
                        m_WriteQueueTimer->start(50);
                }
            }
        }
        else
        {
            //直接发送的写法
            if(data->m_RegisterCount > 1)
            {
                // 写入多个寄存器
                QByteArray request;
                QDataStream stream(&request, QIODevice::WriteOnly);
                stream.setByteOrder(QDataStream::BigEndian);

                // Transaction Identifier
                quint16 transactionId = 0x0001; // Example transaction ID
                stream << transactionId;

                // Protocol Identifier
                quint16 protocolId = 0x0000;
                stream << protocolId;

                // Length Field (will be set later)
                quint16 lengthField = 0;
                stream << lengthField;

                // Unit Identifier
                quint8 unitIdentifier = 0x01;
                stream << unitIdentifier;

                // Function Code
                quint8 functionCode = 0x10; // Write Multiple Registers
                stream << functionCode;

                // Starting Address
                stream << data->m_StartAddress;

                // Quantity of Registers
                stream << data->m_RegisterCount;

                // Byte Count
                quint8 byteCount =  data->m_RegisterCount * 2;
                stream << byteCount;

                // Register Values
                for (quint16 value : data->m_Data) {
                    stream << value;
                }

                // Update Length Field
                lengthField = static_cast<quint16>(request.size() - 6); // Exclude the first 6 bytes (Transaction ID, Protocol ID, Length Field)
                /*  换一种写法 **
            request[4] = (lengthField >> 8) & 0xFF;
            request[5] = lengthField & 0xFF;
            request[5] = lengthField & 0xFF;
            *   流写法 */
                stream.device()->seek(4); // 回到长度字段的位置
                stream << lengthField;
                // Send the request
                qDebug() << "Muli write:" << ByteArraytoQString16bitShow(request);

                WriteQueue.enqueue(request);
                if(!WriteQueue.isEmpty())
                {
                    if(!m_WriteQueueTimer->isActive())
                        m_WriteQueueTimer->start(50);
                }
            }
            else if(data->m_RegisterCount == 1)
            {
                QByteArray request;
                QDataStream stream(&request, QIODevice::WriteOnly);
                stream.setByteOrder(QDataStream::BigEndian);

                // 事务标识符
                quint16 transactionId = 0x0001;
                // 协议标识符
                quint16 protocolId = 0x0000;

                // 长度字段（后续字节数，初始为6，单个寄存器不更新）
                quint16 length = 6;
                // 单元标识符（从站地址）
                quint8 unitId = 0x01;
                // 功能码
                quint8 functionCode = 0x06;
                // 起始地址
                quint16 startingAddress = data->m_StartAddress;
                // 寄存器值
                quint16 registerValue = 0xFFFF;
                if(!data->m_Data.isEmpty())
                    registerValue = data->m_Data.at(0); // 替换为你要写入的值

                // 写入数据
                stream << transactionId << protocolId << length << unitId << functionCode << startingAddress << registerValue;

                // 更新长度字段（6个后续字节：单元标识符、功能码、起始地址、寄存器值）
                //length = 6;
                //stream.device()->seek(4); // 回到长度字段的位置
                //stream << length;

                // 发送请求
                //qDebug() << " sing write:" << ByteArraytoQString16bitShow(request);
                WriteQueue.enqueue(request);
                if(!WriteQueue.isEmpty())
                {
                    if(!m_WriteQueueTimer->isActive())
                        m_WriteQueueTimer->start(50);
                }
            }
        }
#endif

    }
}

void ModBusTcpWorker::slotSetWriteStartAddressAndRegisterCount(int startAddress, int registerCount, QList<quint16> data)
{
    WriteStartAddress = startAddress;
    WriteRegisterCount = registerCount;
    writeData.clear();
    writeData = data;
    writeHoldingRegisters();//开始写入
}

void ModBusTcpWorker::timeoutLoopConnect()
{
    socket->connectToHost(IPAddress, IPPort); // 连接到服务器
}

void ModBusTcpWorker::fristReadHoldingRegisters()
{
    for(auto it = fristReadRegisterInfo.begin(); it != fristReadRegisterInfo.end() ; ++it)
    {
        quint8 functionCodeKey = it.key();
        QList<QPair<int,int> > InputRegistersInfo  = fristReadRegisterInfo[functionCodeKey]; //输入寄存器的信息列表

        for(int i = 0; i <  InputRegistersInfo.size(); i++)
        {
            int inputStartAddress = InputRegistersInfo[i].first;          //本次循环需要读的寄存器的起始地址
            int inputRegisterCount = InputRegistersInfo[i].second;        //本次循环需要读的寄存器的个数

            HandleAndSend(i+functionCodeKey*1000,0x01,functionCodeKey,inputStartAddress,inputRegisterCount);
        }
    }
}

void ModBusTcpWorker::timeoutReadHoldingRegisters()
{

    if(cntSendIndex < SendReadRegister.size())
    {
        if(logcnt %20 == 0)
            qDebug() << "sendData:" << ByteArraytoQString16bitShow(SendReadRegister[cntSendIndex]);
        socket->write( SendReadRegister[cntSendIndex]);
        ++cntSendIndex;
        if(cntSendIndex == SendReadRegister.size())
            cntSendIndex= 0;
    }

    logcnt++;

    /****QMap****
    for(auto it = ReadRegisterInfo.begin(); it != ReadRegisterInfo.end() ; ++it)
    {
        quint8 functionCodeKey = it.key();
        QList<QPair<int,int> > InputRegistersInfo  = ReadRegisterInfo[functionCodeKey]; //输入寄存器的信息列表

        for(int i = 0; i <  InputRegistersInfo.size(); i++)
        {
            int inputStartAddress = InputRegistersInfo[i].first;          //本次循环需要读的寄存器的起始地址
            int inputRegisterCount = InputRegistersInfo[i].second;        //本次循环需要读的寄存器的个数

            HandleAndSend(i+functionCodeKey*100,0x01,functionCodeKey,inputStartAddress,inputRegisterCount);

        }
    }
    *****QMap*******/
}

void ModBusTcpWorker::timeoutWriteQueueRegisters()
{
    if(socket->state() == QAbstractSocket::ConnectedState) // 服务端已连接则读取
    {
        WriteDataQueueIsEmpty = WriteQueue.isEmpty();
        if(WriteDataQueueIsEmpty)//队列为空的时候读消息
        {
            //对列写完发送消息
            if(WriteDataQueueIsEmpty && !WriteDataQueueIsEmptyPre)
            {
                emit sig_WriteDataQueueFinish();
                m_WriteQueueTimer->stop();
            }
        }
        else //队列不为空则先写队列
        {
            /*
            WriteData* writeData = m_WriteDataQueue.dequeue();//弹栈
            slotSetWriteStartAddressAndRegisterCount(writeData->m_StartAddress,
                                                     writeData->m_RegisterCount,
                                                     writeData->m_Data);
                                                     */
            QByteArray writeData = WriteQueue.dequeue();//弹栈
            qDebug() << "writeData:" << ByteArraytoQString16bitShow(writeData);
            socket->write(writeData);
        }
        WriteDataQueueIsEmptyPre = WriteDataQueueIsEmpty;//记录空状态，
    }
}



void ModBusTcpWorker::readHoldingRegisters()
{

}

void ModBusTcpWorker::writeHoldingRegisters()
{
    if(socket->state() == QAbstractSocket::ConnectedState)
    {
        if(WriteRegisterCount > 1)
        {
            // 写入多个寄存器
            QByteArray request;
            QDataStream stream(&request, QIODevice::WriteOnly);
            stream.setByteOrder(QDataStream::BigEndian);

            // Transaction Identifier
            quint16 transactionId = 0x0001; // Example transaction ID
            stream << transactionId;

            // Protocol Identifier
            quint16 protocolId = 0x0000;
            stream << protocolId;

            // Length Field (will be set later)
            quint16 lengthField = 0;
            stream << lengthField;

            // Unit Identifier
            quint8 unitIdentifier = 0x01;
            stream << unitIdentifier;

            // Function Code
            quint8 functionCode = 0x10; // Write Multiple Registers
            stream << functionCode;

            // Starting Address
            stream << WriteStartAddress;

            // Quantity of Registers
            stream << WriteRegisterCount;

            // Byte Count
            quint8 byteCount = WriteRegisterCount * 2;
            stream << byteCount;

            // Register Values
            for (quint16 value : writeData) {
                stream << value;
            }

            // Update Length Field
            lengthField = static_cast<quint16>(request.size() - 6); // Exclude the first 6 bytes (Transaction ID, Protocol ID, Length Field)
            /*  换一种写法 **
            request[4] = (lengthField >> 8) & 0xFF;
            request[5] = lengthField & 0xFF;
            request[5] = lengthField & 0xFF;
            *   流写法 */
            stream.device()->seek(4); // 回到长度字段的位置
            stream << lengthField;
            // Send the request
            qDebug() << " MulWrite:" << ByteArraytoQString16bitShow(request);
            socket->write(request);
        }
        else if(WriteRegisterCount == 1)
        {
            QByteArray request;
            QDataStream stream(&request, QIODevice::WriteOnly);
            stream.setByteOrder(QDataStream::BigEndian);

            // 事务标识符
            quint16 transactionId = 0x0001;
            // 协议标识符
            quint16 protocolId = 0x0000;

            // 长度字段（后续字节数，初始为6，单个寄存器不更新）
            quint16 length = 6;
            // 单元标识符（从站地址）
            quint8 unitId = 0x01;
            // 功能码
            quint8 functionCode = 0x06;
            // 起始地址
            quint16 startingAddress = WriteStartAddress;
            // 寄存器值
            quint16 registerValue = 0xFFFF;
            if(!writeData.isEmpty())
                registerValue = writeData.at(0); // 替换为你要写入的值

            // 写入数据
            stream << transactionId << protocolId << length << unitId << functionCode << startingAddress << registerValue;

            // 更新长度字段（6个后续字节：单元标识符、功能码、起始地址、寄存器值）
            //length = 6;
            //stream.device()->seek(4); // 回到长度字段的位置
            //stream << length;

            // 发送请求
            qDebug() << " singWrite:" << ByteArraytoQString16bitShow(request);
            socket->write(request);
        }
    }
}

void ModBusTcpWorker::FristConHandleData(int RegistersType, int MsgId, QList<quint16> readData)
{

}

void ModBusTcpWorker::HandleData(quint8 RegistersType, quint16 MsgId, QList<quint16> readData)
{
    /****invertBoolList***反转bool  因为1关0开*/
    switch (MsgId) {
    case 300:
    {
        if(readData.size() != 10)
            return;
        //运行开关和6个正转反转
        QList<bool> blist1 =  quint16ToBoolList(readData.at(0));

        /*
        //电机错误屏蔽
        QList<bool> tempBlist2 =  quint16ToBoolList(readData.at(1));
        QList<bool> blist2;
        blist2 << tempBlist2.at(0) << tempBlist2.at(1) << tempBlist2.at(2) ;

        //错误指示
        QList<bool> tempBlist3 =  quint16ToBoolList(readData.at(2));
        QList<bool> blist3;
        blist3 << tempBlist3.at(0) << tempBlist3.at(1) << tempBlist3.at(2) ;
        */

        //电机1-3限位指示1-2  运动指示和匹配完成指示
        QList<bool> blist4 =  quint16ToBoolList(readData.at(3));

         //下标4是步进的方向
        QList<bool> blist5 =  quint16ToBoolList(readData.at(4));


        //下标5为空

        //反射电压、入射电压
        QList<float> flist6 ;
        flist6 << quint16ToFloat(readData.at(6),readData.at(7));
        flist6 << quint16ToFloat(readData.at(8),readData.at(9));


        emit sig_readBoolData(11,blist1);//运行开关和6个正转反转
        //emit sig_readBoolData(12,blist2);//电机错误屏蔽
        //emit sig_readBoolData(13,blist3);//错误指示
        emit sig_readBoolData(14,blist4);//电机1-3限位指示1-2  运动指示、匹配完成和手动匹配
        emit sig_readBoolData(15,blist5);//步进方向
        emit sig_readfloatData(21,flist6);//当前电压
    }
        break;
    case 301:
    {
        if(readData.size() != 6)
            return;
        QList<float> flist1;
        for(int i = 0 ; i< 6; i+=2)
        {
            flist1 << quint16ToFloat(readData.at(i),readData.at(i+1));
        }
        emit sig_readfloatData(22,flist1);//电容1-3容值
    }
        break;
    default:
        break;
    }
}

void ModBusTcpWorker::onConnected()//TCP连接成功
{
    m_Connect->stop();
    fristReadHoldingRegisters();
    m_LoopReadTimer->start(200);
    emit sig_ConnectionState(true);
}

void ModBusTcpWorker::onReadyRead()//TCP读取成功
{
    if(m_RTU)
    {
        ModBusRTUResponse response = HandleRec(socket->readAll());
        // 输出解析结果
        //qDebug() << "Address:" << response.address;
        //qDebug() << "Function Code:" << response.functionCode;
        //qDebug() << "Data:" << response.data;
        //qDebug() << "CRC:" << response.crc;
        int MsgId = 0;
        if(response.data.size() == 10)
        {
            MsgId = 300;
        }
        else if (response.data.size() == 6)
        {
            MsgId = 301;
        }
        HandleData(response.functionCode,MsgId,response.data);
    }
    else
    {
        QByteArray response = socket->readAll();

        if(logcnt % 20 == 0)
            qDebug() << "recData:" <<ByteArraytoQString16bitShow(response);

        QDataStream stream(response);
        stream.setByteOrder(QDataStream::BigEndian); // Modbus TCP使用大端字节序

        quint16 transactionIdentifier;
        quint16 protocolIdentifier;
        quint16 length;
        quint8 unitIdentifier;
        quint8 functionCode;
        quint8 byteCount;

        stream >> transactionIdentifier >> protocolIdentifier >> length >> unitIdentifier >> functionCode >> byteCount;

        if (functionCode == 0x83) {
            qDebug() << "Read Error response received!";
            return;
        }

        if (functionCode ==0x90)
        {
            qDebug() << "Write Error response received!";
            return;
        }

        // 读取线圈状态
        // 输出解析结果
        //qDebug() << "Transaction Identifier:" << transactionIdentifier;
        //qDebug() << "Protocol Identifier:" << protocolIdentifier;
        //qDebug() << "Length:" << length;
        //qDebug() << "Unit Identifier:" << unitIdentifier;
        //qDebug() << "Function Code:" << functionCode;
        //qDebug() << "Byte Count:" << byteCount;
        //    qDebug() << "Datas :" << datas;

        switch (functionCode) {
        case 0x01://线圈
        case 0x02://离散输入
        {
            QList<quint8> datas;
            QList<bool> bList;
            for (int i = 0; i < byteCount; ++i)
            {
                quint8 coilByte;
                stream >> coilByte;
                datas.append(coilByte);
            }
            bList = quint8ListToBoolList(datas);
            //qDebug() << "bList:" << bList;
            //emit sig_readBoolData(transactionIdentifier,bList);
        }
            break;
        case 0x03:
        case 0x04:
        {
            QList<quint16> datas;
            for (int i = 0; i < byteCount / 2; ++i) {
                quint16 value;
                stream >> value;
                datas.append(value);
                //qDebug() << "Register" << i << ":" << value;
            }
            if(logcnt % 20 == 0)
                qDebug() << "Register data:" << datas;
            HandleData(functionCode,transactionIdentifier,datas);
        }
            break;
        default:
            break;
        }
    }



}

void ModBusTcpWorker::onDisConnected()
{
    qDebug() << "onDisConnected";
    //m_Connect->start(1000);
    emit sig_ConnectionState(false);
    m_LoopReadTimer->stop();
}

QByteArray ModBusTcpWorker::HandleAndSend(quint16 transactionId, quint8 unitId, quint8 functionCode, quint16 StartingAddress, quint16 Registers)
{
    if(m_RTU)
    {
        QByteArray frame;
        QDataStream stream(&frame, QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::BigEndian);

        // Slave Address
        stream << static_cast<quint8>( 0x01);

        // Function Code
        stream << functionCode;

        // Starting Address
        stream << StartingAddress;

        // Number of Registers
        stream << Registers;

        // Calculate CRC
        quint16 crc = swapBytes(calculateCRC(frame));
        stream << crc;

        qDebug() << "send:" << ByteArraytoQString16bitShow(frame);
        //socket->write(frame);
        return  frame;
    }
    else
    {
        QByteArray request;
        QDataStream stream(&request, QIODevice::WriteOnly);
        stream.setByteOrder(QDataStream::BigEndian);

        // Transaction ID  事务标识符
        stream << transactionId;

        // Protocol ID 协议标识符
        quint16 protocolId = 0x0000;
        stream << protocolId;

        // Length  长度字段
        quint16 length = 6;
        stream << length;

        // Unit ID 单元标识符
        stream << unitId;

        // Function Code  功能码
        stream << functionCode;

        // Starting Address 起始地址
        stream << StartingAddress;

        // Quantity of Registers  寄存器个数
        stream << Registers;

        //qDebug() << "send:" << ByteArraytoQString16bitShow(request);
        //socket->write(request);
        return  request;
    }

}

ModBusRTUResponse ModBusTcpWorker::HandleRec(QByteArray byteArray)
{
    ModBusRTUResponse response;
    QDataStream stream(byteArray);
    stream.setByteOrder(QDataStream::BigEndian); // ModBus RTU使用大端模式

    // 读取设备地址和功能码
    stream >> response.address >> response.functionCode;

    // 读取数据长度（对于读命令的响应，数据长度是字节）
    quint8 dataLength;
    stream >> dataLength;

    // 读取数据
    for (int i = 0; i < dataLength / 2; ++i) { // 数据长度除以2是因为每个寄存器是2字节
        quint16 registerValue;
        stream >> registerValue;
        response.data.append(registerValue);
    }

    // 读取CRC校验
    quint16 crcHigh, crcLow;
    stream >> crcHigh >> crcLow;
    response.crc = (crcHigh << 8) | crcLow; // 组合高低字节

    return response;
}


#else




ModBusTcpWorker::ModBusTcpWorker(QObject *parent) : QObject(parent),
    m_ProName(""),m_DevType(0),IPAddress("127.0.0.1"),IPPort(502),
    WriteStartAddress(120),WriteRegisterCount(10),connectCnt(0),m_TimerCnt(0),
    WriteDataQueueIsEmpty(true),WriteDataQueueIsEmptyPre(true)
{
    /*
    modbusClient = new QModbusTcpClient(this);


    // 连接stateChanged信号
    connect(modbusClient,&QModbusTcpClient::stateChanged,this,&ModBusTcpWorker::slot_stateChanged);

    // 连接errorOccurred信号
    connect(modbusClient, &QModbusTcpClient::errorOccurred,this,&ModBusTcpWorker::slot_errorOccurred);
    */

    //循环读取寄存器的数据
    m_LoopReadTimer = new QTimer(this);
    connect(m_LoopReadTimer,&QTimer::timeout,this,&ModBusTcpWorker::timeoutReadHoldingRegisters);
//    timer->start(200);//开始读寄存器  等线程start则定时器start
}

ModBusTcpWorker::~ModBusTcpWorker()
{
    m_LoopReadTimer->stop();
    //析构的时候断开连接
    if(modbusClient->state() == QModbusTcpClient::ConnectedState)
    {
        modbusClient->disconnectDevice();
    }
}

//设置项目名称和设备编号，预留记录用
void ModBusTcpWorker::slotSetProNameDevType(QString proName, int DevType)
{
    m_ProName = proName;
    m_DevType = DevType;
    /*******未使用********************************
    //根据设备分读寄存器的起始地址和寄存器的个数
    switch (m_DevType) {
    case 0:
    {
        QList<QPair<int,int> > InputRegistersInfo;
        InputRegistersInfo << QPair<int,int>(20,6);

        QList<QPair<int,int> > HoldingRegistersInfo;
        HoldingRegistersInfo << QPair<int,int>(2,2);

        ReadRegisterInfo.insert(4,InputRegistersInfo);  // 输入寄存器的起始地址 和 寄存器的个数
        ReadRegisterInfo.insert(3,HoldingRegistersInfo);// 保持寄存器的起始地址 和 寄存器的个数
    }
        break;
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    {
        QList<QPair<int,int> > InputRegistersInfo;
        InputRegistersInfo << QPair<int,int>(4,2)  << QPair<int,int>(20,22);

        //QList<QPair<int,int> > HoldingRegistersInfo;
        //HoldingRegistersInfo << QPair<int,int>(2,2);

        ReadRegisterInfo.insert(4,InputRegistersInfo);  // 输入寄存器的起始地址 和 寄存器的个数
        //ReadRegisterInfo.insert(3,HoldingRegistersInfo);// 保持寄存器的起始地址 和 寄存器的个数

     }
        break;

    default:
        break;

    }
    ********未使用********************************/
}


//设置参数并连接服务器
bool ModBusTcpWorker::startModBusTcpConnect()
{
    modbusClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, IPPort); // 设置Modbus端口
    modbusClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter, IPAddress); // 设置Modbus服务器地址
    modbusClient->setTimeout(500); // 设置超时
    modbusClient->setNumberOfRetries(3); // 设置重试次数
    modbusClient->connectDevice(); // 连接到服务器

    if (modbusClient->state() != QModbusTcpClient::ConnectedState)
    {
        ++connectCnt;
        if(connectCnt%150 == 0)
            qDebug() << "Modbus连接失败" << " 连接IP:" <<IPAddress;
        return false;
    }
    else
    {
        return true;
    }
}

//解析float数据
void ModBusTcpWorker::HandleData(int RegistersType,int MsgId, QList<quint16> readData)
{
//    qDebug() << "msgId:" << MsgId;
//     qDebug() << "readData:" << readData;

    /****invertBoolList***反转bool  因为1关0开*/
    switch (MsgId) {
    case 1:
    {
        if(readData.size() != 10)
            return;
        //运行开关和6个正转反转
        QList<bool> blist1 =  quint16ToBoolList(readData.at(0));

        /*
        //电机错误屏蔽
        QList<bool> tempBlist2 =  quint16ToBoolList(readData.at(1));
        QList<bool> blist2;
        blist2 << tempBlist2.at(0) << tempBlist2.at(1) << tempBlist2.at(2) ;

        //错误指示
        QList<bool> tempBlist3 =  quint16ToBoolList(readData.at(2));
        QList<bool> blist3;
        blist3 << tempBlist3.at(0) << tempBlist3.at(1) << tempBlist3.at(2) ;
        */

        //电机1-3限位指示1-2  运动指示和匹配完成指示
        QList<bool> blist4 =  quint16ToBoolList(readData.at(3));

         //下标4是步进的方向
        QList<bool> blist5 =  quint16ToBoolList(readData.at(4));


        //下标5为空

        //反射电压、入射电压
        QList<float> flist6 ;
        flist6 << quint16ToFloat(readData.at(6),readData.at(7));
        flist6 << quint16ToFloat(readData.at(8),readData.at(9));


        emit sig_readBoolData(11,blist1);//运行开关和6个正转反转
        //emit sig_readBoolData(12,blist2);//电机错误屏蔽
        //emit sig_readBoolData(13,blist3);//错误指示
        emit sig_readBoolData(14,blist4);//电机1-3限位指示1-2  运动指示、匹配完成和手动匹配
        emit sig_readBoolData(15,blist5);//步进方向
        emit sig_readfloatData(21,flist6);//当前电压
    }
        break;
    case 2:
    {
        if(readData.size() != 6)
            return;
        QList<float> flist1;
        for(int i = 0 ; i< 6; i+=2)
        {
            flist1 << quint16ToFloat(readData.at(i),readData.at(i+1));
        }
        emit sig_readfloatData(22,flist1);//电容1-3容值
    }
        break;
    default:
        break;
    }

#if 0
    switch (m_DevType) {                         //区分设备信息，是总控还是分机
    case 0:                                      //总控设备
    {
        if(RegistersType == 4 && MsgId == 1)     //第1条浮点数消息的解析
        {
            if(readData.size() != 6)
                return;

            /****解析出浮点数*****/
            QList<float> fDatas;

            //入射电压
            fDatas << quint16ToFloat(readData.at(0),readData.at(1));

            //反射电压
            fDatas << quint16ToFloat(readData.at(2),readData.at(3));

            //驻波比
            fDatas << quint16ToFloat(readData.at(4),readData.at(5));

            emit sig_readfloatData(MsgId,fDatas);
        }

        if(RegistersType == 3 && MsgId == 1)       //第1条bool消息的解析
        {
            if(readData.size() != 2)
                return;
            QList<bool> blist1 =  quint16ToBoolList(readData.at(0));
            QList<bool> blist2 =  quint16ToBoolList(readData.at(1));


            QList<bool> blist;
            blist << blist1.at(0) << blist1.at(1); //存入复位和选频的数据
            for(int i = 0; i <= 13 ; i ++)         //存入1~8号分机故障  入射超值 反射超值 驻波比超值  光使能  射频开关 驻波比故障
            {
                blist << blist2.at(i);
            }

        //    qDebug() << "blist:" << blist;
            emit sig_readBoolData(MsgId,blist);
        }

    }
        break;
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:                                            //1~8分机设备
    {
         if(RegistersType == 4)                        //输入寄存器
         {
            if(MsgId == 1)                             //输入寄存器的第一条消息
            {
                if(readData.size() != 2)
                    return;
                QList<bool> blist1 =  quint16ToBoolList(readData.at(0));
                QList<bool> blist2 =  quint16ToBoolList(readData.at(1));


                QList<bool> blist;
                blist << blist1.at(0) << blist1.at(1)
                      << blist1.at(2) << blist1.at(3); //存入温度1~4
                for(int i = 0; i <= 9 ; i ++)          //存入电流1~4 入射 反射 运行状态 水流 总控使能 驻波比
                {
                    blist << blist2.at(i);
                }
                emit sig_readBoolData(MsgId,blist);
            }
            else if(MsgId == 2)                        //输入寄存器的第二条消息
            {
                if(readData.size() != 22)
                    return;

                /****解析出浮点数*****/
                QList<float> fDatas;

                /*存入 入射电压 反射电压 电源电压
                       电流1 电流2 电流3 电流4
                       温度1 温度2 温度3 温度4 */
                for(int i = 0 ; i < 22 ; i+=2)
                {
                    fDatas << quint16ToFloat(readData.at(i),readData.at(i+1));
                }
                emit sig_readfloatData(MsgId,fDatas);
            }
         }
    }
        break;

    default:
        break;

    }
#endif

}

//解析bool数据
/*
void ModBusTcpWorker::HandleData2(QList<quint16> readData)
{
    if(readData.size() != 2)
        return;
    QList<bool> blist1 =  quint16ToBoolList(readData.at(0));
    QList<bool> blist2 =  quint16ToBoolList(readData.at(1));


    QList<bool> blist;
    blist << blist1.at(0) << blist1.at(1); //存入复位和选频的数据
    for(int i = 0; i <= 13 ; i ++)         //存入1~8号分机故障  入射超值 反射超值 驻波比超值  光使能  射频开关 驻波比故障
    {
        blist << blist2.at(i);
    }

//    qDebug() << "blist:" << blist;
    emit sig_readBoolData(blist);

}
*/

//设置IP和端口号，如果已有IP和端口在运行则切换
void ModBusTcpWorker::slotSetIPPort(QString address,short port)
{
    if(IPAddress !=address || IPPort!=port)
    {

        // 检查对象是否存在，如果存在则销毁并重新创建
        if (modbusClient) {
            // 销毁当前对象并重新创建一个新的 QModbusTcpClient 对象
            modbusClient.reset(new QModbusTcpClient());
        }
        else {
            modbusClient = QSharedPointer<QModbusTcpClient>::create();
        }


        // 连接stateChanged信号
        connect(modbusClient.data(),&QModbusTcpClient::stateChanged,this,&ModBusTcpWorker::slot_stateChanged);
        // 连接errorOccurred信号
        connect(modbusClient.data(), &QModbusTcpClient::errorOccurred,this,&ModBusTcpWorker::slot_errorOccurred);

        IPAddress = address;
        IPPort = port;
        modbusClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, IPPort); // 设置Modbus端口
        modbusClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter, IPAddress); // 设置Modbus服务器地址
        modbusClient->setTimeout(300); // 设置超时
        modbusClient->setNumberOfRetries(2); // 设置重试次数
    }
}

void ModBusTcpWorker::slotFristReadStartAddressAndRegisterCount(QList<int> startAddress, QList<int> registerCount, int RegisterType)
{

}

//设置读取寄存器的起始地址和寄存器的个数
void ModBusTcpWorker::slotSetReadStartAddressAndRegisterCount(QList<int> startAddress, QList<int> registerCount,int RegisterType)
{
    ReadStartAddress = startAddress;
    ReadRegisterCount = registerCount;
//    readHoldingRegisters();
    if(ReadStartAddress.size() == ReadRegisterCount.size())
    {
        QList<QPair<int,int> > InputRegistersInfo;
//        InputRegistersInfo << QPair<int,int>(4,2)  << QPair<int,int>(20,22);
        for(int i = 0 ; i < ReadStartAddress.size(); i++)
        {
            InputRegistersInfo << QPair<int,int>(ReadStartAddress.at(i),ReadRegisterCount.at(i));
        }
        ReadRegisterInfo.insert(RegisterType,InputRegistersInfo);
        qDebug() << "ReadRegisterInfo:" << ReadRegisterInfo;
    }
    else
    {
        qDebug() << "寄存器的起始地址和输入地址的个数不对";
    }
}

void ModBusTcpWorker::slotStartConnection(bool isStart)//开始读寄存器
{
    if(isStart)
        m_LoopReadTimer->start(20);
    else
    {
        m_LoopReadTimer->stop();
        if(modbusClient->state() == QModbusTcpClient::ConnectedState)
            modbusClient->disconnectDevice();
    }
}

//添加数据到写数据的队列中
void ModBusTcpWorker::slotAddWriteQueue(WriteData* data)
{
    if(modbusClient->state() == QModbusDevice::ConnectedState) // 服务端已连接则读取
    {
        m_WriteDataQueue.enqueue(data);
    }
}
//设置写入寄存器的起始地址和寄存器的个数
void ModBusTcpWorker::slotSetWriteStartAddressAndRegisterCount(int startAddress, int registerCount,QList<quint16> data)
{
    WriteStartAddress = startAddress;
    WriteRegisterCount = registerCount;
    writeData.clear();
    writeData = data;
    writeHoldingRegisters();//开始写入
}


void ModBusTcpWorker::slot_stateChanged(QModbusDevice::State state)
{
    if (state == QModbusDevice::UnconnectedState)
    {
        emit sig_ConnectionState(false);
    }
    else if(state == QModbusDevice::ConnectedState)
    {
        emit sig_ConnectionState(true);
    }
}

void ModBusTcpWorker::slot_errorOccurred(QModbusDevice::Error error)
{
    Q_UNUSED(error)
    emit sig_ConnectionState(false);
}


void ModBusTcpWorker::timeoutReadHoldingRegisters()
{
    //qDebug() << "20ms：" << QDateTime::currentDateTime();
    /******************当前的模式适用于断电记忆存在上位机中，通信连接后上位机写消息队列给下位机使用*******/
    ++m_TimerCnt;
    if(modbusClient->state() == QModbusDevice::ConnectedState) // 服务端已连接则读取
    {
        WriteDataQueueIsEmpty = m_WriteDataQueue.isEmpty();
        if(WriteDataQueueIsEmpty)//队列为空的时候读消息
        {
            //对列写完发送消息
            if(WriteDataQueueIsEmpty && !WriteDataQueueIsEmptyPre)
                emit sig_WriteDataQueueFinish();

            if(m_TimerCnt % 10 == 0)   //读的周期设置 周20   200毫秒读一次
            {
                readHoldingRegisters();
            }
        }
        else //队列不为空则先写队列
        {
            WriteData* writeData = m_WriteDataQueue.dequeue();//弹栈

            slotSetWriteStartAddressAndRegisterCount(writeData->m_StartAddress,
                                                     writeData->m_RegisterCount,
                                                     writeData->m_Data);
        }
        WriteDataQueueIsEmptyPre = WriteDataQueueIsEmpty;//记录空状态，
    }
    else                                                       // 服务端未连接则重新连接
    {
        if(m_TimerCnt % 10 == 0)
            emit sig_ConnectionState(startModBusTcpConnect()); // 发送在线消息
    }
}

void ModBusTcpWorker::timeoutWriteQueueRegisters()
{

}

void ModBusTcpWorker::fristReadHoldingRegisters()
{

}

//读取寄存器的值
/*
void ModBusTcpWorker::ReadValue()
{
    if(modbusClient->state() == QModbusDevice::ConnectedState)
    {
        QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, 0, 1); // 读取一个寄存器
        if (auto *reply = modbusClient->sendReadRequest(readUnit, 1))
        {
            if (!reply->isFinished())
            {
                connect(reply,&QModbusReply::finished,this,&ModBusTcpWorker::ReceiveData);
                return;
            }
            reply->deleteLater();
        }
        else {
            qDebug()<< "提前退出";
        }
    }
}
*/

void ModBusTcpWorker::readHoldingRegisters()
{
    //获取不同设备的多个输入寄存器的起始地址和寄存器个数 组
    if(ReadRegisterInfo.contains(4))                                      //key==4是输入寄存器的信息储存  如果存在输入寄存器的信息
    {
        QList<QPair<int,int> > InputRegistersInfo  = ReadRegisterInfo[4]; //输入寄存器的信息列表

        for(int i = 0; i <  InputRegistersInfo.size(); i++)
        {
            int inputStartAddress = InputRegistersInfo[i].first;          //本次循环需要读的寄存器的起始地址
            int inputRegisterCount = InputRegistersInfo[i].second;        //本次循环需要读的寄存器的个数

            //第一段读取—输入寄存器*********算传统代码看做一个整体******************************************************
            QModbusDataUnit readUnit1(QModbusDataUnit::InputRegisters, inputStartAddress, inputRegisterCount);
            if (auto *reply = modbusClient->sendReadRequest(readUnit1, 1))
            { // 假设服务器地址为 1
                if (!reply->isFinished())
                {
                    QObject::connect(reply, &QModbusReply::finished, this, [=]()
                    {
                        if (reply->error() == QModbusDevice::NoError)
                        {
                            const QModbusDataUnit unit = reply->result();
                            QList<quint16> readData;
                            for (quint16 i = 0; i < unit.valueCount(); ++i)
                            {
                                quint16 value = unit.value(i);
                                readData << value;
                                //                        qDebug() << "Register1" << i << ":" << value;
                            }

                            /*****测试通信通断在这里读到数值就发送至主线程******/
                            /*****正式版解析完后再发送至主线程****************/
                            HandleData(4,i+1,readData);                   //解析数据 形参 传4为输入寄存器  消息的ID 和数据
                            /*****测试通信通断在这里读到数值就发送至主线程******/
                            /*****正式版解析完后再发送至主线程****************/
                        }
                        else
                        {
                            qDebug() << "Read float Data error:" << reply->errorString() << " IP:" << IPAddress;
                        }
                        reply->deleteLater();
                    });
                }
                else
                {
                    delete reply;
                }
            }
            else
            {
                qDebug() << "Read float Data request error:" << modbusClient->errorString() << " IP:" << IPAddress;
            }
            //第一段读取—输入寄存器*********算传统代码看做一个整体******************************************************

        }
    }


    //获取不同设备的多个保持寄存器的起始地址和寄存器个数 组
    if(ReadRegisterInfo.contains(3))                                       //key==3是保持寄存器的信息储存  如果存在保持寄存器的信息
    {
        QList<QPair<int,int> > HoldingRegistersInfo  = ReadRegisterInfo[3];//保持寄存器的信息列表
        for(int i = 0; i <  HoldingRegistersInfo.size(); i++)
        {
            int holdingStartAddress = HoldingRegistersInfo[i].first;       //本次循环需要读的寄存器的起始地址
            int holdingRegisterCount = HoldingRegistersInfo[i].second;     //本次循环需要读的寄存器的个数

            //第二段读取——保持寄存器*******************算传统代码看做一个整体**************************************************
            QModbusDataUnit readUnit2(QModbusDataUnit::HoldingRegisters, holdingStartAddress, holdingRegisterCount);
            if (auto *reply = modbusClient->sendReadRequest(readUnit2, 1))
            { // 假设服务器地址为 1
                if (!reply->isFinished())
                {
                    QObject::connect(reply, &QModbusReply::finished, this, [=]()
                    {
                        if (reply->error() == QModbusDevice::NoError)
                        {
                            const QModbusDataUnit unit = reply->result();
                            QList<quint16> readData;
                            for (quint16 i = 0; i < unit.valueCount(); ++i)
                            {
                                quint16 value = unit.value(i);
                                readData << value;
//                                qDebug() << "Register2" << i << ":" << value;
                            }

                            /*****测试通信通断在这里读到数值就发送至主线程******/
                            /*****正式版解析完后再发送至主线程****************/
                            HandleData(3,i+1,readData);               //解析数据 形参 传3为保持寄存器  消息的ID 和数据
                            /*****测试通信通断在这里读到数值就发送至主线程******/
                            /*****正式版解析完后再发送至主线程****************/

                        }
                        else
                        {
                            qDebug() << "Read bool Data error:" << reply->errorString() << " IP:" << IPAddress
                                     << " StartAddress:" << holdingStartAddress << " RegisterCount:" << holdingRegisterCount;
                        }
                        reply->deleteLater();
                    });
                }
                else
                {
                    delete reply;
                }
            }
            else
            {
                qDebug() << "Read bool Data request error:" << modbusClient->errorString() << " IP:" << IPAddress;
            }
            //第二段读取——保持寄存器*******************算传统代码看做一个整体**************************************************
        }
    }
}

void ModBusTcpWorker::writeHoldingRegisters()
{
    if(modbusClient->state() == QModbusDevice::ConnectedState)
    {
        QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, WriteStartAddress, WriteRegisterCount); // 写入一个寄存器
//        writeUnit.setValue(0,999);
        /*
        for(int i = 0 ; i < 10 ; ++i)
        {
            writeUnit.setValue(i,i);
        }
        */
        for(int i = 0; i < writeData.size(); i++) {
            writeUnit.setValue(i,writeData.at(i));
        }

        reply = modbusClient->sendWriteRequest(writeUnit, 1);
        if (reply) {
            if (!reply->isFinished()) {
                connect(reply, &QModbusReply::finished, this, [&]() {
                    if (reply->error() == QModbusDevice::NoError) {
                        // 写入成功
                        qDebug() << "Write success:" << WriteStartAddress << " " << WriteRegisterCount << " " << writeData;
                    } else {
                        // 写入失败，处理错误
                        qDebug() << "Write error:" << reply->errorString() <<" " << WriteStartAddress << " " << WriteRegisterCount << " " << writeData;;
                    }
                    //reply->deleteLater();//成员变量可以不使用异步删除
                });
            } else {
                // 立即处理回复
                if (reply->error() != QModbusDevice::NoError) {
                    qDebug() << "Write response error:" << reply->errorString();
                }
                //reply->deleteLater();//成员变量可以不使用异步删除
            }
        }
        else
        {
            qDebug() << "Write request error:" << modbusClient->errorString();
        }
    }
}
#endif
